package day4;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

//通过反射编写一个任意对象调用任意方法
public
class TestInvokeMethod {
    //method(方法名,形参.class[])
    //method.invoke(对象，实参...)
    //参数一：调用方法的对象 参数二：方法名 参数三：方法调用传递的实参  返回值：表方法的返回值
    public static Object base(Object o,String name,Object... args){
        Object result= null;
        try {
            Class c=o.getClass();
            Class[] cs=new Class[args.length];
            for (int i=0;i<args.length;i++){
                cs[i]=args[i].getClass();
            }
            Method m=c.getDeclaredMethod(name,cs);//args.getClass() 获取参数的类型
            m.setAccessible(true);
            result = m.invoke(o,args);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return result;
    }
 //bug:虽然解决了基本类型的问题，但是没有解决方法重载的问题
     public static Object base1(Object o,String name,Object... args){
        Class c=o.getClass();
        Class[] cs=null;
        for(Method m:c.getDeclaredMethods()){
            if(m.getName().equals(name)){
                cs=m.getParameterTypes();
                break;
            }
        }
        Object result= null;
         try {
             Method m=c.getDeclaredMethod(name,cs);
             m.setAccessible(true);
             result=m.invoke(o,args);
         } catch (NoSuchMethodException e) {
            e.printStackTrace();
         } catch (IllegalAccessException e) {
             e.printStackTrace();
         } catch (InvocationTargetException e) {
             e.printStackTrace();
         }
         return result;
     }

    public static
    void main(String[] args) {
        Student1 s=new Student1();
        Object result = new TestInvokeMethod().base(s,"study");
        System.out.println(result);
        Object result1 = new TestInvokeMethod().base1(s,"math", 10, 20);
        System.out.println(result1);
        Teacher t=new Teacher();
        Object result2 = new TestInvokeMethod().base1(t,"teach");
        System.out.println(result2);
        Object result3 = new TestInvokeMethod().base1(t,"age",58);
        System.out.println(result3);
    }
}
